package com.tarena.lbs.basic.web.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.basic.web.dao.repository.UserRepository;
import com.tarena.lbs.basic.web.dao.repository.UserTagsRepository;
import com.tarena.lbs.basic.web.thread.AuthenticationUtil;
import com.tarena.lbs.common.basic.util.RandomUserName;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.param.UserParam;
import com.tarena.lbs.pojo.basic.param.UserTagsParam;
import com.tarena.lbs.pojo.basic.po.UserPO;
import com.tarena.lbs.pojo.basic.po.UserTagsPO;
import com.tarena.lbs.pojo.basic.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserTagsRepository userTagsRepository;
    public void doRegister(UserParam userParam) throws BusinessException {
        //1.使用phone 校验是否已经存在电话号了
        checkPhoneExists(userParam);
        //2.封装数据 写入数据库
        UserPO poParam=param2po(userParam);
        userRepository.save(poParam);
    }

    private UserPO param2po(UserParam userParam) {
        UserPO po=new UserPO();
        BeanUtils.copyProperties(userParam,po);
        //1.user状态 0未激活|没有绑定过标签 1已激活|已经登录绑定过标签 前端在登录之后查询详情 使用这个字段
        //来决定是否给当前登录的用户展示 选择标签页面 0 展示 1 不展示
        po.setStatus(0);
        //2.昵称 用户名称 给一个随机名字
        String randomName = RandomUserName.createRandomName();//[老,大,小] [赵钱孙李周吴郑王]
        po.setUserName(randomName);
        po.setNickName(randomName);
        //3.统计数据 注册时间
        po.setRegTime(new Date());
        return po;
    }

    private void checkPhoneExists(UserParam userParam) throws BusinessException {
        String phone = userParam.getPhone();
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("phone",phone);
        long count=userRepository.count(queryWrapper);
        Asserts.isTrue(count>0,new BusinessException("-2","手机号已存在"));
    }

    public UserVO detail() throws BusinessException {
        //1.通过认证 拿到userPrinciple的id
        UserPrinciple userPrinciple= AuthenticationUtil.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证解析失败"));
        //2.通过持久层 获取user的完整信息 避免password返回
        UserPO po = userRepository.getById(userPrinciple.getId());
        Asserts.isTrue(po==null,new BusinessException("-2","用户不存在"));
        UserVO vo=new UserVO();
        BeanUtils.copyProperties(po,vo);
        vo.setPassword(null);
        return vo;
    }
    //关注一下 这个方法中操作删除 新增 更新写操作的事务一致性
    @Transactional(rollbackFor = Exception.class)
    public void userTagsBind(UserTagsParam userTagsParam) throws BusinessException {
        //1.拿到登录认证对象的userId
        UserPrinciple userPrinciple= AuthenticationUtil.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证解析失败"));
        Integer userId=userPrinciple.getId();
        //2.保证 每次绑定标签 都是该用户 最新数据 先删除该用户已有历史数据
        //delete from lbs_user_tags where user_id=#{}
        removeUserTags(userId);
        //3.从参数中 解析数据 执行批量绑定
        //lbs_user_tags写数据 记录该用户绑定的所有标签
        //insert into lbs_user_tags (user_id,tag_id) values(#{id},)
        String[] tagIds = userTagsParam.getTagIds().split(",");//1,5,2,8
        //将tagIds转换成批量写入的UserTagsPO数组 一次性让reposiotry写入数据库
        List<UserTagsPO> poParams= Arrays.stream(tagIds).map(tagId->{
            UserTagsPO po=new UserTagsPO();
            po.setUserId(userId);
            po.setTagId(Integer.valueOf(tagId));
            return po;
        }).collect(Collectors.toList());
        userTagsRepository.saveBatch(poParams);//mybatis-plus在业务层封装的一个批量操作 底层用户mapper
        //批量数据list int 每次批量执行数量 100 一次性批量 10000 每次 200条 分50次完成
        /*for (String tagId : tagIds) {
            UserTagsPO poParam=new UserTagsPO();
            poParam.setUserId(userId);
            poParam.setTagId(Integer.valueOf(tagId));
            userTagsRepository.save(poParam);
        }*/
        //4.绑定成功后 修改用户的状态 status=>1
        UserPO userPo=new UserPO();
        userPo.setId(userId);
        userPo.setStatus(1);
        userRepository.updateById(userPo);//传递一个userPO 提供id属性 where id=#{} 其他非空属性
        //mybatis-plus拼接set  update lbs_user set status=1 where id=#{userId}
    }

    private void removeUserTags(Integer userId) {
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("user_id",userId);
        userTagsRepository.remove(queryWrapper);
    }
}
